﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using SLControlLibrary.Resources.Controls.Calendar.OutlookCalendar.BusinessObjects;
using SLControlLibrary.Resources.Controls.Calendar.OutlookCalendar.Common;
using SLControlLibrary.Resources.Controls.Calendar.OutlookCalendar.DataAccess;
using SLControlLibrary.Resources.Controls.Calendar.OutlookCalendar.ViewModel;

namespace SLControlLibrary.Resources.Controls.Calendar.OutlookCalendar
{
    public class ucCalendar : Control
    {
        #region Dependency Variables

        private static readonly DependencyProperty CurrentDateProperty = DependencyProperty.Register("CurrentDate", typeof(DateTime), typeof(ucCalendar), new PropertyMetadata(DateTime.Now, new PropertyChangedCallback(CurrentDate_Changed)));
        private static readonly DependencyProperty CurrentDateViewProperty = DependencyProperty.Register("CurrentDateView", typeof(Enumerations.DateView), typeof(ucCalendar), new PropertyMetadata(Enumerations.DateView.Day, new PropertyChangedCallback(CurrentDateView_Changed)));
        private static readonly DependencyProperty AppointmentsProperty = DependencyProperty.Register("Appointments", typeof(AppointmentList), typeof(ucCalendar), new PropertyMetadata(null, new PropertyChangedCallback(Appointments_Changed)));
        private static readonly DependencyProperty ShowAppointmentProperty = DependencyProperty.Register("ShowAppointment", typeof(Visibility), typeof(ucCalendar), new PropertyMetadata(Visibility.Collapsed, new PropertyChangedCallback(ShowAppointment_Changed)));
        private static readonly DependencyProperty TimeSlotsPerHourProperty = DependencyProperty.Register("TimeSlotsPerHour", typeof(SLControlLibrary.Resources.Common.Enumerations.TimeSlotsPerHour), typeof(ucCalendar), new PropertyMetadata(SLControlLibrary.Resources.Common.Enumerations.TimeSlotsPerHour.Fifteen, new PropertyChangedCallback(TimeSlotsPerHour_Changed)));
        private static readonly DependencyProperty HoursPerDayProperty = DependencyProperty.Register("HoursPerDay", typeof(SLControlLibrary.Resources.Common.Enumerations.HoursPerDay), typeof(ucCalendar), new PropertyMetadata(SLControlLibrary.Resources.Common.Enumerations.HoursPerDay.TwentyFour, new PropertyChangedCallback(HoursPerDay_Changed)));

        #endregion Dependency Variables

        #region Dependency Properties

        public DateTime CurrentDate
        {
            get { return (DateTime)this.GetValue(CurrentDateProperty); }
            set { this.SetValue(CurrentDateProperty, value); }
        }

        public Enumerations.DateView CurrentDateView
        {
            get { return (Enumerations.DateView)this.GetValue(CurrentDateViewProperty); }
            set { this.SetValue(CurrentDateViewProperty, value); }
        }

        public AppointmentList Appointments
        {
            get { return (AppointmentList)this.GetValue(AppointmentsProperty); }
            set { this.SetValue(AppointmentsProperty, value); }
        }

        public Visibility ShowAppointment
        {
            get { return (Visibility)this.GetValue(ShowAppointmentProperty); }
            set { this.SetValue(ShowAppointmentProperty, value); }
        }

        public SLControlLibrary.Resources.Common.Enumerations.TimeSlotsPerHour TimeSlotsPerHour
        {
            get { return (SLControlLibrary.Resources.Common.Enumerations.TimeSlotsPerHour)this.GetValue(TimeSlotsPerHourProperty); }
            set { this.SetValue(TimeSlotsPerHourProperty, value); }
        }

        public SLControlLibrary.Resources.Common.Enumerations.HoursPerDay HoursPerDay
        {
            get { return (SLControlLibrary.Resources.Common.Enumerations.HoursPerDay)this.GetValue(HoursPerDayProperty); }
            set { this.SetValue(HoursPerDayProperty, value); }
        }

        #endregion Dependency Properties

        #region Dependency Events

        #region CurrentDate_Changed

        private static void CurrentDate_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnCurrentDate_Changed(e);
        }

        #endregion CurrentDate_Changed

        #region CurrentDateView_Changed

        private static void CurrentDateView_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnCurrentDateView_Changed(e);
        }

        #endregion CurrentDateView_Changed

        #region Appointments_Changed

        private static void Appointments_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnAppointments_Changed(e);
        }

        #endregion Appointments_Changed

        #region ShowAppointment_Changed

        private static void ShowAppointment_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnShowAppointment_Changed(e);
        }

        #endregion ShowAppointment_Changed

        #region TimeSlotsPerHour_Changed

        private static void TimeSlotsPerHour_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnTimeSlotsPerHour_Changed(e);
        }

        #endregion TimeSlotsPerHour_Changed

        #region HoursPerDay_Changed

        private static void HoursPerDay_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucCalendar).OnHoursPerDay_Changed(e);
        }

        #endregion HoursPerDay_Changed

        #endregion Dependency Events

        #region Variables

        private ucHeader _Header = null;
        private ucDaysOfWeek _DaysOfWeek = null;
        private ucContent _Content = null;
        private ucEditAppointment _Appointment = null;
        private AppointmentProvider _AppProvider = null;
        private bool AppointmentClosing = false;

        #endregion Variables

        #region Constructor

        public ucCalendar()
        {
            DefaultStyleKey = typeof(ucCalendar);
        }

        #endregion Constructor

        #region Methods

        #region OnApplyTemplate

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _Header = (ucHeader)base.GetTemplateChild("_Header");

            if (_Header == null) return;

            _Header.Day_Clicked += new EventHandler(Header_Day_Clicked);
            _Header.WorkWeek_Clicked += new EventHandler(Header_WorkWeek_Clicked);
            _Header.FullWeek_Clicked += new EventHandler(Header_FullWeek_Clicked);
            _Header.Month_Clicked += new EventHandler(Header_Month_Clicked);
            _Header.Year_Clicked += new EventHandler(Header_Year_Clicked);
            _Header.Date_Changed += new EventHandler(Header_Date_Changed);

            _DaysOfWeek = (ucDaysOfWeek)base.GetTemplateChild("_DaysOfWeek");

            if (_DaysOfWeek == null) return;

            _DaysOfWeek.DayOfWeek_Clicked += new EventHandler(DayOfWeek_Clicked);

            _Content = (ucContent)base.GetTemplateChild("_Content");

            if (_Content == null) return;

            _Content.MonthWeek_Clicked += new EventHandler(Content_MonthWeek_Clicked);
            _Content.MonthDay_Clicked += new EventHandler(Content_MonthDay_Clicked);
            _Content.AddAppointment_Clicked += new EventHandler(Content_AddAppointment_Clicked);

            _Appointment = (ucEditAppointment)base.GetTemplateChild("_Appointment");

            if (_Appointment == null) return;

            _Appointment.Appointment_Closed += new EventHandler(Appointment_Closed);
            _Appointment.Appointment_Submited += new EventHandler(Appointment_Submited);

            SetBindings();

            _AppProvider = new AppointmentProvider();
            _AppProvider.RequestXML("");
            _AppProvider.OptionsLoaded += new EventHandler(AppProvider_OptionsLoaded);
        }

        #endregion OnApplyTemplate

        #region OnCurrentDate_Changed

        protected virtual void OnCurrentDate_Changed(DependencyPropertyChangedEventArgs e)
        {
            CurrentDate = (DateTime)e.NewValue;
        }

        #endregion OnCurrentDate_Changed

        #region OnCurrentDateView_Changed

        protected virtual void OnCurrentDateView_Changed(DependencyPropertyChangedEventArgs e)
        {
            CurrentDateView = (Enumerations.DateView)e.NewValue;
        }

        #endregion OnCurrentDateView_Changed

        #region OnAppointments_Changed

        protected virtual void OnAppointments_Changed(DependencyPropertyChangedEventArgs e)
        {
            Appointments = (AppointmentList)e.NewValue;
        }

        #endregion OnAppointments_Changed

        #region OnShowAppointment_Changed

        protected virtual void OnShowAppointment_Changed(DependencyPropertyChangedEventArgs e)
        {
            ShowAppointment = (Visibility)e.NewValue;
        }

        #endregion OnShowAppointment_Changed

        #region OnTimeSlotsPerHour_Changed

        protected virtual void OnTimeSlotsPerHour_Changed(DependencyPropertyChangedEventArgs e)
        {
            TimeSlotsPerHour = (SLControlLibrary.Resources.Common.Enumerations.TimeSlotsPerHour)e.NewValue;
        }

        #endregion OnTimeSlotsPerHour_Changed

        #region OnHoursPerDay_Changed

        protected virtual void OnHoursPerDay_Changed(DependencyPropertyChangedEventArgs e)
        {
            HoursPerDay = (SLControlLibrary.Resources.Common.Enumerations.HoursPerDay)e.NewValue;
        }

        #endregion OnHoursPerDay_Changed

        #region SetBindings

        private void SetBindings()
        {
            var vm = new OutlookVM { CurrentDateView = Enumerations.DateView.Day, CurrentDate = DateTime.Now };
            this.DataContext = vm;

            Binding b1 = new Binding() { Path = new PropertyPath("CurrentDateView"), Mode = BindingMode.TwoWay, Source = vm };
            this.SetBinding(ucCalendar.CurrentDateViewProperty, b1);

            _DaysOfWeek.SetBinding(ucDaysOfWeek.CurrentDateViewProperty, b1);
            _Header.SetBinding(ucHeader.CurrentDateViewProperty, b1);
            _Content.SetBinding(ucContent.CurrentDateViewProperty, b1);

            Binding b2 = new Binding() { Path = new PropertyPath("CurrentDate"), Mode = BindingMode.TwoWay, Source = vm };
            this.SetBinding(ucCalendar.CurrentDateProperty, b2);

            _DaysOfWeek.SetBinding(ucDaysOfWeek.CurrentDateProperty, b2);
            _Header.SetBinding(ucHeader.CurrentDateProperty, b2);
            _Content.SetBinding(ucContent.CurrentDateProperty, b2);

            Binding b3 = new Binding() { Path = new PropertyPath("Appointments"), Mode = BindingMode.TwoWay, Source = vm };
            this.SetBinding(ucCalendar.AppointmentsProperty, b3);

            _Content.SetBinding(ucContent.AppointmentsProperty, b3);

            Binding b4 = new Binding() { Path = new PropertyPath("TimeSlotsPerHour"), Mode = BindingMode.TwoWay, Source = vm };
            this.SetBinding(ucCalendar.TimeSlotsPerHourProperty, b4);

            _Content.SetBinding(ucContent.TimeSlotsPerHourProperty, b4);

            Binding b5 = new Binding() { Path = new PropertyPath("HoursPerDay"), Mode = BindingMode.TwoWay, Source = vm };
            this.SetBinding(ucCalendar.HoursPerDayProperty, b5);

            _Content.SetBinding(ucContent.HoursPerDayProperty, b5);
        }

        #endregion SetBindings

        #endregion Methods

        #region Events

        #region AppProvider_OptionsLoaded

        private void AppProvider_OptionsLoaded(object sender, EventArgs e)
        {
            Appointments = (sender as AppointmentProvider)._OptionsProvider.AppointmentList;
        }

        #endregion AppProvider_OptionsLoaded

        #region DaysOfWeek

        #region DayOfWeek_Clicked

        private void DayOfWeek_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.Day;
            CurrentDate = (sender as ucDayOfWeekContentItem).Date;
        }

        #endregion DayOfWeek_Clicked

        #endregion DaysOfWeek

        #region Header

        #region Header_Day_Clicked

        private void Header_Day_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.Day;
            CurrentDate = DateTime.Now;
        }

        #endregion Header_Day_Clicked

        #region Header_WorkWeek_Clicked

        private void Header_WorkWeek_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.WorkWeek;
            CurrentDate = DateTime.Today;
        }

        #endregion Header_WorkWeek_Clicked

        #region Header_FullWeek_Clicked

        private void Header_FullWeek_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.FullWeek;
            CurrentDate = DateTime.Today;
        }

        #endregion Header_FullWeek_Clicked

        #region Header_Month_Clicked

        private void Header_Month_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.Month;
        }

        #endregion Header_Month_Clicked

        #region Header_Year_Clicked

        private void Header_Year_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.Year;
        }

        #endregion Header_Year_Clicked

        #region Header_Date_Changed

        private void Header_Date_Changed(object sender, EventArgs e)
        {
            CurrentDate = (DateTime)sender;
        }

        #endregion Header_Date_Changed

        #endregion Header

        #region Content

        #region Content_MonthDay_Clicked

        private void Content_MonthDay_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.Day;
            CurrentDate = (sender as ucMonthContentItem).CurrentDate;
        }

        #endregion Content_MonthDay_Clicked

        #region Content_MonthWeek_Clicked

        private void Content_MonthWeek_Clicked(object sender, EventArgs e)
        {
            CurrentDateView = Enumerations.DateView.WorkWeek;
            CurrentDate = (DateTime)sender;
        }

        #endregion Content_MonthWeek_Clicked

        #region Content_AddAppointment_Clicked

        private void Content_AddAppointment_Clicked(object sender, EventArgs e)
        {
            if (!AppointmentClosing)
                ShowAppointment = Visibility.Visible;

            AppointmentClosing = false;

            _Appointment.CurrentAppointment = new Appointment();
            _Appointment.CurrentAppointment.IsNewAppointment = true;
        }

        #endregion Content_AddAppointment_Clicked

        #endregion Content

        #region Appointment

        #region Appointment_Submited

        private void Appointment_Submited(object sender, EventArgs e)
        {
            ShowAppointment = Visibility.Collapsed;

            _AppProvider.SaveXML("", (Appointment)sender);
        }

        #endregion Appointment_Submited

        #region Appointment_Closed

        private void Appointment_Closed(object sender, EventArgs e)
        {
            AppointmentClosing = true;
            ShowAppointment = Visibility.Collapsed;
        }

        #endregion Appointment_Closed

        #endregion Appointment

        #endregion Events
    }
}